# -*- coding: utf-8 -*-
# Author: kimus

import gtk
from lvmman.gui import GladeWindow
import gobject
from pylvm import lvm
from pylvm.i18n import _

import os

import goocanvas
import random
import math

class Main(GladeWindow):
	TREEVIEW_COLUMNS = [_('Name'), _('Block Device'), _('Size')]
	DISK_ICON = gtk.gdk.pixbuf_new_from_file('/usr/share/icons/Human/16x16/devices/drive-harddisk.png')

	def __startvalidate__(self):
		if os.getuid() != 0:
			self.show_messagedialog(_("Error"), _("Please restart the application with root permissions!"), gtk.MESSAGE_ERROR)
			return False
		return True
	
	def __validate__(self):
		return True
    
	def __start__(self):
    	# create references to controls
		self.treeview = self.glade.get_widget('treeview')
		self.combobox = self.glade.get_widget('cboVolumes')
		self.drawarea = self.glade.get_widget('diskimage')
		self.butadd   = self.glade.get_widget('butAdd')
		self.butrem   = self.glade.get_widget('butRemove')
		self.menuadd  = self.glade.get_widget('menuAdd')
		self.menurem  = self.glade.get_widget('menuRemove')
		
		# initializations needed
		self.canvas = None
		self.aboutDialog = None
		self.current_vg = None
		
		# event binds
		self.glade.signal_autoconnect({
            "on_menuQuit_activate":	self.quit,
            "on_menuAbout_activate":	self.about,
            "on_cboVolumes_changed":	self.combobox_changed,
            "on_diskimage_resize":	self.drawarea_resized,
            "on_butAdd_clicked":	self.add_logical_volume,
            "on_butRemove_clicked":	self.remove_logical_volume,
            "on_treeview_changed":	self.treeview_changed,
            None: None
        })

		# initialize LVM 
		lvm.load()
		
		# initialize componets
		self.initialize_combobox()
		self.initialize_treeview()
		self.set_volume(0)

	def initialize_treeview(self):
		tv = self.treeview
		
		idx = 1
		for col in Main.TREEVIEW_COLUMNS:
			c = gtk.TreeViewColumn(col)
			tv.append_column(c)
			
			if idx == 1:
				pixbf = gtk.CellRendererPixbuf()
				c.pack_start(pixbf, True)
				c.add_attribute(pixbf, 'pixbuf', 0)

			# create a CellRendererText to render the data
			cell = gtk.CellRendererText()

			# add the cell to the column and allow it to expand
			c.pack_start(cell, True)

			# set the cell "text" attribute to the correct column - retrieve text
			# from that column in treestore
			c.add_attribute(cell, 'text', idx)
			
			idx = idx + 1

		# make it searchable
		#tv.set_search_column(0)

		# Allow sorting on the column
		#col0.set_sort_column_id(0)

		# Allow drag and drop reordering of rows
		#tv.set_reorderable(True)

		tv.show()
		
	def initialize_combobox(self):
		cb = self.combobox
		
		lststore = gtk.ListStore(
            gtk.gdk.Pixbuf, #Icon
            gobject.TYPE_STRING, #Volume/Device
            gobject.TYPE_STRING, #Size
        )
		
		# create a CellRendererText to render the data
		pixbf = gtk.CellRendererPixbuf()
		vcell = gtk.CellRendererText()
		scell = gtk.CellRendererText()

		# add the cells
		cb.pack_start(pixbf, True)
		cb.pack_start(vcell, True)
		cb.pack_start(scell, True)

		# set the cell "text" attribute to column 1 - retrieve text
		# from that column in list store
		cb.add_attribute(pixbf, 'pixbuf', 0)
		cb.add_attribute(vcell, 'text', 1)
		cb.add_attribute(scell, 'text', 2)
		
		
		
		for vg in lvm.vgs:
			lststore.append([Main.DISK_ICON, vg.name, '(%s)' % vg.total])

		cb.set_model(lststore)
		cb.set_active(0)

	
	def set_add_enabled(self, enabled=True):
		self.butadd.set_sensitive(enabled)
		self.menuadd.set_sensitive(enabled)
		
	def set_rem_enabled(self, enabled=True):
		self.butrem.set_sensitive(enabled)
		self.menurem.set_sensitive(enabled)
		
	def set_volume(self, index):
		self.current_vg = lvm.vgs[index]
		self.load_volume()
	
	def load_volume(self):
		self.set_add_enabled(self.current_vg.free_extents > 0)
		self.set_rem_enabled(False)
		self.show_volume_disks(self.current_vg)
		self.draw_volume_parts(self.current_vg)
	
	def show_volume_disks(self, vg):
		tv = self.treeview
		
		# create a TreeStore with one string column to use as the model
		treestore = gtk.TreeStore(
            gtk.gdk.Pixbuf, #Icon
            gobject.TYPE_STRING, #Name
            gobject.TYPE_STRING, #Device
            gobject.TYPE_STRING, #Size
            gobject.TYPE_PYOBJECT   #Object
        )
		
		pvs = treestore.append(None, [None, _("Physical Disks"), None, None, None])
		lvs = treestore.append(None, [None, _("Logical Disks"), None, None, None])
		for pv in vg.pvs:
			treestore.append(pvs, [Main.DISK_ICON, pv.name, pv.path, pv.total, None])
		for lv in vg.lvs:
			treestore.append(lvs, [Main.DISK_ICON, lv.name, lv.path, lv.total, lv])
		
		tv.set_model(treestore)
		tv.expand_all()
		
	def draw_volume_parts(self, vg):
		area = self.drawarea
		width, height = self.app.get_size()
		width = width - 2
		height = 62
		full_height = height + 32
		y = 32
		
		if self.canvas == None:
			self.canvas = goocanvas.Canvas()
			area.add(self.canvas)
		
		#self.canvas.set_size_request(width, full_height)
		self.canvas.set_bounds(0, 0, width, full_height)
		root = self.canvas.get_root_item()
		
		goocanvas.Rect(
            parent=root,
            x=0, y=0, width=width, height=full_height,
            fill_color="white",
            stroke_color="white", line_width=2.0
        )
		
		text = _("Name: %s\nSize: %s   Unallocated: %s") % (vg.name, vg.total, vg.free) if vg.free_extents > 0 else _("Name: %s\nSize: %s") % (vg.name, vg.total)
		goocanvas.Text(
            text=text,
            font="Sans 8", x=4, y=4,
            parent=root
        )
		
		lvs = {}
		x = 0
		for lv in vg.lvs:
			if lv.name not in lvs:
				w = math.floor((lv.total_extents * width) / vg.total_extents)
				lvs[lv.name] = w
				
				goocanvas.Rect(
                    parent=root,
                    x=x, y=y, width=w, height=height,
                    fill_color="steelblue",
                    stroke_color="white", line_width=2.0
                )
		
				#goocanvas.Text(
				#		text="%s\n%s" % (lv.path, lv.total),
				#		font="Sans 8",
				#		x=(w / 2) + x, y=height / 2,
				#		anchor=gtk.ANCHOR_CENTER,
				#		parent=root
				#	)				
				x = x + w
				
		if vg.free_extents > 0:
			w = math.floor((vg.free_extents * width) / vg.total_extents)
			goocanvas.Rect(
                parent=root,
                x=x, y=y, width=w, height=height,
                fill_color="grey",
                stroke_color="white", line_width=2.0
            )
                   
		self.canvas.show()
			

	def get_selected_lv(self):
		tv = self.treeview
		model, iter = tv.get_selection().get_selected()
		if iter:
			lv = model.get_value(iter, 4)
			if lv:
				return lv
		return None

	def reload_volume(self):
		lvm.reload()
		self.current_vg = lvm.get_vgname(self.current_vg.name)
		self.load_volume()

	# event handling
	def quit(self, * args):
		gtk.main_quit()
	
	def add_logical_volume(self, * args):
		from gui.lvcreatedialog import LVCreateDialog
		dialog = LVCreateDialog(self.current_vg)
		dialog.show(self.app)
		
		self.reload_volume()
		
	def remove_logical_volume(self, * args):
		lv = self.get_selected_lv()
		response = self.show_messagedialog(
            _("Delete Logical Volume"),
            _("Are you sure you want to delete the selected Logical Volume (%s)?\nAll data will be DESTROYED!!") % lv.name,
            gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO
        )
		if response == gtk.RESPONSE_YES:
			lvm.remove_lv(lv)
			self.reload_volume()
		
	def drawarea_resized(self, * args):
		if self.current_vg != None:
			self.draw_volume_parts(self.current_vg)

	def combobox_changed(self, * args):
		self.set_volume(self.combobox.get_active())
		
	def treeview_changed(self, * args):
		lv = self.get_selected_lv()
		self.set_rem_enabled(lv != None)	

	def about(self, * args):
		if self.aboutDialog is None:
			self.aboutDialog = gtk.AboutDialog()
			self.aboutDialog.set_transient_for(self.app)
			self.aboutDialog.set_name(_("LVM Manager"))
			self.aboutDialog.set_version('0.1')
			self.aboutDialog.set_website('http://code.google.com/p/python-lvm/')
			self.aboutDialog.set_authors([
                'kimus <kimus@ubuntu-pt.org>',
            ])
			self.aboutDialog.set_translator_credits(_('translator-credits'))
			self.aboutDialog.set_comments(_('LVM Manager.'))
			self.aboutDialog.set_copyright(_('Copyright © 2009 kimus'))
			self.aboutDialog.set_wrap_license(True)
			self.aboutDialog.set_license(_('This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.'))
			self.aboutDialog.set_logo(Main.DISK_ICON)
			
			self.aboutDialog.connect('response', self.about_close_cb)
			self.aboutDialog.connect('close', self.about_close_cb)
			self.aboutDialog.connect('delete_event', self.about_close_cb)
		self.aboutDialog.show()
		
	def about_close_cb(self, widget, * args):
		self.aboutDialog.hide()
		return True
